package client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import utils.ExceptionUtils;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

/**
 * Creates XML RPC Clients and provides methods to interact with one.
 * @date March 14, 2011
 * @author Eric Kisner
 */
public class RPCConnection {

    private String URL;
    private String handler;
    private XmlRpcClient client;

    public RPCConnection( String URL, String handler ) {
        if( URL == null ) {
            throw new RuntimeException( "You must provide the URL to the server." );
        } else if( handler == null ) {
            throw new RuntimeException( "You must provide the server's service name." );
        }
        this.URL = URL;
        this.handler = handler;
        initClient();
    }

    /**
     * Initializes a new XML RPC Client by connecting to the server.
     */
    private void initClient() {
        try {
            client = new XmlRpcClient( URL );
        } catch( MalformedURLException malformed ) {
            ExceptionUtils.handleException( malformed, this.getClass() );
            throw new RuntimeException( "The server URL you have provided is invalid. Please provide a valid one." );
        } catch( Exception e ) {
            ExceptionUtils.handleException( e, this.getClass() );
            throw new RuntimeException( "There was an error setting up an XML RPC Client.\n" + e.getMessage() );
        }
    }

    /**
     * Remote method call for the current service on the current server.
     * @param params The parameters for executing the method.
     * @param methodName The method name that we want to call.
     * @return The Object that is returned from the method.
     */
    public Object executeMethod( String methodName, Vector params ) throws XmlRpcException, IOException {
        if( params == null ) {
            return client.execute( handler + "." + methodName, new Vector() );
        } else {
            return client.execute( handler + "." + methodName, params );
        }
    }

    /**
     * Get a List of results from method calls.
     *
     * @param methodNames The name of all methods we want to call.
     * 
     * @param params An array of parameters (as Vectors) we need to inject into the method call.
     * 
     * @return A List of Objects that are results of each method call.
     */
    public List<Object> getResults( List<String> methodNames, List<Vector> params ) throws XmlRpcException,
                                                                                           IOException {
        List<Object> ret = new ArrayList<Object>();
        for( int i = 0; i < methodNames.size(); i++ ) {
            ret.add( executeMethod( methodNames.get( i ), params.get( i ) ) );
        }
        return ret;
    }
}
